package com.chuangdun.flutter.plugin.alarm

import android.app.AlarmManager
import android.content.Context
import android.content.Intent
import android.database.sqlite.SQLiteException
import android.os.Build
import android.provider.Settings
import android.util.Log
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import java.util.Calendar

const val TAG = "AlarmPlugin"

/** FlutterAlarmPlugin */
class FlutterAlarmPlugin : FlutterPlugin, MethodCallHandler {

    private lateinit var channel: MethodChannel
    private lateinit var context: Context
    private lateinit var alarmManager: AlarmManager
    private lateinit var databaseHelper: AlarmDatabaseHelper

    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        context = flutterPluginBinding.applicationContext
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter_alarm")
        channel.setMethodCallHandler(this)
        databaseHelper = AlarmDatabaseHelper(context)
        alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        when (call.method) {
            "getPlatformVersion" -> {
                result.success("Android ${Build.VERSION.RELEASE}")
            }

            "checkPermission" -> {
                checkPermission(result)
            }

            "requestPermission" -> {
                requestPermission(result)
            }

            "setAlarm" -> {
                setAlarm(call, result)
            }

            "setRepeatingAlarm" -> {
                setRepeatingAlarm(call, result)
            }

            "cancelAlarm" -> {
                cancelAlarm(call, result)
            }

            "cancelAlarmsByTag" -> {
                cancelAlarmsByTag(call, result)
            }

            "cancelAllAlarms" -> {
                cancelAllAlarms(call, result)
            }

            "getAlarmsByTag" -> {
                getAlarmsByTag(call, result)
            }

            "getAlarmByAlarmId" -> {
                getAlarmByAlarmId(call, result)
            }

            "getAllAlarms" -> {
                getAllAlarms(call, result)
            }

            else -> {
                result.notImplemented()
            }
        }
    }

    private fun checkPermission(result: Result) {
        var hasAllPermissions = true

        // 检查系统窗口权限（用于后台弹出对话框）
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(context)) {
                hasAllPermissions = false
            }
        }

        // 检查精确闹钟权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            if (!alarmManager.canScheduleExactAlarms()) {
                hasAllPermissions = false
            }
        }

        result.success(hasAllPermissions)
    }

    private fun requestPermission(result: Result) {
        // 首先检查系统窗口权限（最重要，用于后台弹窗）
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(context)) {
                // 引导用户到系统设置页面授权悬浮窗权限
                val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION).apply {
                    flags = Intent.FLAG_ACTIVITY_NEW_TASK
                }
                context.startActivity(intent)
                result.success(false) // 返回false，用户需要手动授权
                return
            }
        }

        // 检查精确闹钟权限 (Android 12+)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            if (!alarmManager.canScheduleExactAlarms()) {
                // 引导用户到设置页面
                val intent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM)
                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                context.startActivity(intent)
                // 返回false，因为用户需要手动授权
                result.success(false)
                return
            }
        }
        // 所有权限都已授予
        result.success(true)
    }


    private fun setAlarm(call: MethodCall, result: Result) {
        try {
            val alarmData = call.arguments as HashMap<String, Any>
            val alarmId = alarmData["alarm_id"] as String
            val tag = alarmData["tag"] as String
            val date = alarmData["date"] as String
            val hour = alarmData["hour"] as Int
            val minute = alarmData["minute"] as Int
            val title = alarmData["title"] as String
            val body = alarmData["body"] as String
            // 判断数据库中是否已经存在相同的alarm_id和tag的闹钟数据
            val existAlarm = databaseHelper.getAlarmByAlarmId(alarmId, tag)
            if (existAlarm != null) {
                val errorMsg = "不允许添加重复闹钟:${alarmId}."
                Log.w(TAG, errorMsg)
                result.success(
                    mapOf(
                        "status" to false, "data" to null, "msg" to errorMsg
                    )
                )
                return
            }
            
            // 使用 DateUtils 解析日期和构建完整时间
            val calendar = DateUtils.buildDateTime(date, hour, minute)
            if (calendar == null) {
                val errorMsg = "日期格式错误,无法添加闹钟."
                Log.e(TAG, errorMsg)
                result.success(
                    mapOf(
                        "status" to false, "data" to null, "msg" to errorMsg
                    )
                )
                return
            }
            
            // 如果指定时间已过 则添加失败.
            if (calendar.timeInMillis <= System.currentTimeMillis()) {
                val errorMsg = "设定时间已过,无法添加闹钟."
                Log.w(TAG, errorMsg)
                result.success(
                    mapOf(
                        "status" to false, "data" to null, "msg" to errorMsg
                    )
                )
                return
            }
            val alarmModel = AlarmModel(
                id = null,
                alarmId = alarmId,
                tag = tag,
                date = date,
                hour = hour,
                minute = minute,
                title = title,
                body = body,
                repeating = false
            )

            // 保存闹钟信息到数据库
            val id = databaseHelper.addAlarm(alarmModel)
            if (id <= 0) {
                val errorMsg = "闹钟数据写入失败."
                Log.e(TAG, errorMsg)
                result.success(
                    mapOf(
                        "status" to false, "data" to null, "msg" to errorMsg
                    )
                )
                return
            }
            alarmModel.id = id
            // 设置闹钟，使用AlarmManager.setAlarmClock以提供更好的用户体验
            val intent = AlarmReceiver.createAlarmIntent(context, tag, alarmId, title, body, false)
            val requestCode = AlarmReceiver.getRequestCode(tag, alarmId)
            val pendingIntent =
                AlarmReceiver.createBroadcastPendingIntent(context, requestCode, intent)
            
            // 创建显示在时钟应用中的信息
            val alarmInfo = AlarmManager.AlarmClockInfo(calendar.timeInMillis, pendingIntent)
            
            // 使用setAlarmClock设置闹钟
            alarmManager.setAlarmClock(alarmInfo, pendingIntent)
            val successMsg = "闹钟设定成功."
            Log.i(TAG, "$successMsg ID: $alarmId, Time: ${DateUtils.formatDateTime(calendar)}")
            result.success(
                mapOf(
                    "status" to true, "data" to alarmModel.toMap(), "msg" to successMsg
                )
            )
        } catch (e: SQLiteException) {
            val errorMsg = "数据库操作失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to false, "data" to null, "msg" to errorMsg))
        } catch (e: Exception) {
            val errorMsg = "闹钟设定失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to false, "data" to null, "msg" to errorMsg))
        }
    }

    private fun setRepeatingAlarm(call: MethodCall, result: Result) {
        try {
            val alarmData = call.arguments as HashMap<String, Any>
            val alarmId = alarmData["alarm_id"] as String
            val tag = alarmData["tag"] as String
            val hour = alarmData["hour"] as Int
            val minute = alarmData["minute"] as Int
            val title = alarmData["title"] as String
            val body = alarmData["body"] as String
            // 判断数据库中是否已经存在相同的alarm_id和tag的闹钟数据
            val existAlarm = databaseHelper.getAlarmByAlarmId(alarmId, tag)
            if (existAlarm != null) {
                val errorMsg = "不允许添加重复闹钟:${alarmId}."
                Log.w(TAG, errorMsg)
                result.success(
                    mapOf(
                        "status" to false, "data" to null, "msg" to errorMsg
                    )
                )
                return
            }
            val calendar = Calendar.getInstance()
            calendar.set(Calendar.HOUR_OF_DAY, hour)
            calendar.set(Calendar.MINUTE, minute)
            calendar.set(Calendar.SECOND, 0)
            calendar.set(Calendar.MILLISECOND, 0)
            // 如果指定时间已过，则设置为明天
            if (calendar.timeInMillis <= System.currentTimeMillis()) {
                calendar.add(Calendar.DAY_OF_MONTH, 1)
            }
            val alarmModel = AlarmModel(
                id = null,
                alarmId = alarmId,
                tag = tag,
                date = null,
                hour = hour,
                minute = minute,
                title = title,
                body = body,
                repeating = true
            )

            // 保存闹钟信息到数据库
            val id = databaseHelper.addAlarm(alarmModel)
            if (id <= 0) {
                val errorMsg = "闹钟数据写入失败."
                Log.e(TAG, errorMsg)
                result.success(
                    mapOf(
                        "status" to false, "data" to null, "msg" to errorMsg
                    )
                )
                return
            }
            alarmModel.id = id
            // 设置重复闹钟，使用AlarmManager.setAlarmClock以提供更好的用户体验
            val intent = AlarmReceiver.createAlarmIntent(context, tag, alarmId, title, body, true)
            val requestCode = AlarmReceiver.getRequestCode(tag, alarmId)
            val pendingIntent =
                AlarmReceiver.createBroadcastPendingIntent(context, requestCode, intent)
            
            // 创建显示在时钟应用中的信息
            val alarmInfo = AlarmManager.AlarmClockInfo(calendar.timeInMillis, pendingIntent)
            
            // 使用setAlarmClock设置闹钟
            alarmManager.setAlarmClock(alarmInfo, pendingIntent)
            val successMsg = "闹钟设定成功."
            Log.i(TAG, "$successMsg ID: $alarmId, Next Time: ${DateUtils.formatDateTime(calendar)} (Repeating)")
            result.success(
                mapOf(
                    "status" to true, "data" to alarmModel.toMap(), "msg" to successMsg
                )
            )
        } catch (e: SQLiteException) {
            val errorMsg = "数据库操作失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to false, "data" to null, "msg" to errorMsg))
        } catch (e: Exception) {
            val errorMsg = "闹钟设定失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to false, "data" to null, "msg" to errorMsg))
        }
    }


    private fun cancelAlarmsByTag(call: MethodCall, result: Result) {
        try {
            val arguments = call.arguments as HashMap<String, Any>
            val tag = arguments["tag"] as String
            val allAlarms = databaseHelper.getAlarmsByTag(tag)
            var cancelCount = 0
            for (alarmModel in allAlarms) {
                val tag = alarmModel.tag
                val alarmId = alarmModel.alarmId
                val title = alarmModel.title
                val body = alarmModel.body
                val repeating = alarmModel.repeating
                val requestCode = AlarmReceiver.getRequestCode(tag, alarmId)
                val intent =
                    AlarmReceiver.createAlarmIntent(context, tag, alarmId, title, body, repeating)
                val pendingIntent =
                    AlarmReceiver.createBroadcastPendingIntent(context, requestCode, intent)
                alarmManager.cancel(pendingIntent)
                cancelCount++
            }
            // 清空所有闹钟信息
            val deleted = databaseHelper.deleteAlarmsByTag(tag)
            if (deleted) {
                val successMsg = "闹钟取消成功."
                Log.i(TAG, "$successMsg Tag: $tag, Count: $cancelCount")
                result.success(mapOf("status" to true, "data" to null, "msg" to successMsg))
            } else {
                val warnMsg = "闹钟已取消，但数据库记录删除失败."
                Log.w(TAG, warnMsg)
                result.success(mapOf("status" to true, "data" to null, "msg" to warnMsg))
            }
        } catch (e: SQLiteException) {
            val errorMsg = "数据库操作失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to false, "data" to null, "msg" to errorMsg))
        } catch (e: Exception) {
            val errorMsg = "闹钟取消失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to false, "data" to null, "msg" to errorMsg))
        }
    }

    private fun getAlarmsByTag(call: MethodCall, result: Result) {
        try {
            val arguments = call.arguments as HashMap<String, Any>
            val tag = arguments["tag"] as String
            val alarmList = databaseHelper.getAlarmsByTag(tag)
            val alarmMapList = alarmList.map { it.toMap() }
            val successMsg = "查询成功."
            Log.d(TAG, "$successMsg Tag: $tag, Count: ${alarmList.size}")
            result.success(mapOf("status" to true, "data" to alarmMapList, "msg" to successMsg))
        } catch (e: SQLiteException) {
            val errorMsg = "数据库查询失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(
                mapOf(
                    "status" to false, "data" to emptyList<Map<String, Any>>(), "msg" to errorMsg
                )
            )
        } catch (e: Exception) {
            val errorMsg = "查询失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(
                mapOf(
                    "status" to false, "data" to emptyList<Map<String, Any>>(), "msg" to errorMsg
                )
            )
        }
    }

    private fun getAlarmByAlarmId(call: MethodCall, result: Result) {
        try {
            val arguments = call.arguments as HashMap<String, Any>
            val alarmId = arguments["alarm_id"] as String
            val tag = arguments["tag"] as String
            val alarm = databaseHelper.getAlarmByAlarmId(alarmId, tag)
            val successMsg = "查询成功."
            if (alarm != null) {
                Log.d(TAG, "$successMsg ID: $alarmId, Tag: $tag")
            } else {
                Log.d(TAG, "$successMsg 未找到闹钟 ID: $alarmId, Tag: $tag")
            }
            result.success(mapOf("status" to true, "data" to alarm?.toMap(), "msg" to successMsg))
        } catch (e: SQLiteException) {
            val errorMsg = "数据库查询失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to true, "data" to null, "msg" to errorMsg))
        } catch (e: Exception) {
            val errorMsg = "查询失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to true, "data" to null, "msg" to errorMsg))
        }
    }

    private fun cancelAlarm(call: MethodCall, result: Result) {
        try {
            val arguments = call.arguments as HashMap<String, Any>
            val tag = arguments["tag"] as String
            val alarmId = arguments["alarm_id"] as String
            val alarmModel = databaseHelper.getAlarmByAlarmId(alarmId, tag)
            if (alarmModel == null) {
                val warnMsg = "未找到要取消的闹钟: ID=$alarmId, Tag=$tag"
                Log.w(TAG, warnMsg)
                // 即使数据库中没有，也尝试取消可能存在的 PendingIntent
                val requestCode = AlarmReceiver.getRequestCode(tag, alarmId)
                val title = ""
                val body = ""
                val repeating = false
                val intent =
                    AlarmReceiver.createAlarmIntent(context, tag, alarmId, title, body, repeating)
                val pendingIntent =
                    AlarmReceiver.createBroadcastPendingIntent(context, requestCode, intent)
                alarmManager.cancel(pendingIntent)
                result.success(mapOf("status" to false, "data" to null, "msg" to warnMsg))
                return
            }
            
            val requestCode = AlarmReceiver.getRequestCode(tag, alarmId)
            val title = alarmModel.title
            val body = alarmModel.body
            val repeating = alarmModel.repeating
            val intent =
                AlarmReceiver.createAlarmIntent(context, tag, alarmId, title, body, repeating)
            val pendingIntent =
                AlarmReceiver.createBroadcastPendingIntent(context, requestCode, intent)
            alarmManager.cancel(pendingIntent)
            // 从数据库中删除闹钟信息
            val deleted = databaseHelper.deleteAlarmByAlarmId(alarmId, tag)
            if (deleted) {
                val successMsg = "闹钟取消成功."
                Log.i(TAG, "$successMsg ID: $alarmId, Tag: $tag")
                result.success(mapOf("status" to true, "data" to null, "msg" to successMsg))
            } else {
                val warnMsg = "闹钟已取消，但数据库记录删除失败."
                Log.w(TAG, warnMsg)
                result.success(mapOf("status" to true, "data" to null, "msg" to warnMsg))
            }
        } catch (e: SQLiteException) {
            val errorMsg = "数据库操作失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to false, "data" to null, "msg" to errorMsg))
        } catch (e: Exception) {
            val errorMsg = "闹钟取消失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to false, "data" to null, "msg" to errorMsg))
        }
    }

    private fun cancelAllAlarms(call: MethodCall, result: Result) {
        try {
            val allAlarms = databaseHelper.getAllAlarms()
            var cancelCount = 0
            for (alarmModel in allAlarms) {
                val tag = alarmModel.tag
                val alarmId = alarmModel.alarmId
                val title = alarmModel.title
                val body = alarmModel.body
                val repeating = alarmModel.repeating
                val requestCode = AlarmReceiver.getRequestCode(tag, alarmId)
                val intent =
                    AlarmReceiver.createAlarmIntent(context, tag, alarmId, title, body, repeating)
                val pendingIntent =
                    AlarmReceiver.createBroadcastPendingIntent(context, requestCode, intent)
                alarmManager.cancel(pendingIntent)
                cancelCount++
            }
            // 清空所有闹钟信息
            val deleted = databaseHelper.deleteAllAlarms()
            if (deleted) {
                val successMsg = "闹钟取消成功."
                Log.i(TAG, "$successMsg Total Count: $cancelCount")
                result.success(mapOf("status" to true, "data" to null, "msg" to successMsg))
            } else {
                val warnMsg = "闹钟已取消，但数据库记录删除失败."
                Log.w(TAG, warnMsg)
                result.success(mapOf("status" to true, "data" to null, "msg" to warnMsg))
            }
        } catch (e: SQLiteException) {
            val errorMsg = "数据库操作失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to false, "data" to null, "msg" to errorMsg))
        } catch (e: Exception) {
            val errorMsg = "闹钟取消失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(mapOf("status" to false, "data" to null, "msg" to errorMsg))
        }
    }

    private fun getAllAlarms(call: MethodCall, result: Result) {
        try {
            val alarmList = databaseHelper.getAllAlarms()
            val alarmMapList = alarmList.map { it.toMap() }
            val successMsg = "查询成功."
            Log.d(TAG, "$successMsg Total Count: ${alarmList.size}")
            result.success(mapOf("status" to true, "data" to alarmMapList, "msg" to successMsg))
        } catch (e: SQLiteException) {
            val errorMsg = "数据库查询失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(
                mapOf(
                    "status" to false, "data" to emptyList<Map<String, Any>>(), "msg" to errorMsg
                )
            )
        } catch (e: Exception) {
            val errorMsg = "查询失败: ${e.message}"
            Log.e(TAG, errorMsg, e)
            result.success(
                mapOf(
                    "status" to false, "data" to emptyList<Map<String, Any>>(), "msg" to errorMsg
                )
            )
        }
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
    }
}
